Typically it is not possible to modify a computer program, or a program class, while the program or class is running, i.e., during runtime. However, there are occasions when program modification during runtime is desirable.
For example, the performance of a computer system running an application, such as the performance of a networked system running an application written in the Java programming language, can be affected by many variables. In order to determine the operating condition of an application, a so-called “diagnostic probe” can be used. Such a probe can be used to monitor various aspects or operating parameters of the application as it runs, for example, to gather statistics regarding application operation. The probe can be written in the programming language of the application. In general, a diagnostic probe captures event information with regard to a running application as the events occur.
In connection with an application running on a network, such as one implemented in a Java-based environment such as Websphere, there may be many instances of Websphere in which the application runs. In order to monitor system performance, such as to identify the source of a performance problem, a diagnostic probe might be installed on the system as it is running to capture system events for analysis. A probe might be useful in gathering such data at runtime, for example, because the performance of a particular application method might vary based on the arguments that are passed to the method. However, something else in an object's immediate environment in the code, which the probe would not be able to detect, might also adversely affect its operation.
One common data capture approach using a probe is to capture timing information for an application method. Data regarding the start of the method, the end of the method, and the method's performance can be captured by the probe. However, the probe may not be able to detect everything about an object's environment. For example, a particular field in an object may have an effect on a method call involving that object that cannot be detected by the probe. That this can have an effect on the performance of the system that may not be revealed by the probe. Therefore, the information captured by the probe does not give a complete picture of the conditions affecting the operation of the method, and thus the performance of the system. What is needed is a way to capture such information, in order to better analyze and understand the factors affecting the performance of the method.
In the prior art, there are two approaches available to achieve this goal. Both approaches are problematic in that they consume significant development, testing, and maintenance resources. The first approach requires the development of many lines of Java code to implement the bytecode instrumentation necessary to use the application programming interface (API) of the application. Such instrumentation involves the addition of bytecodes to application methods for gathering data to be utilized by diagnostic tools. Examples of such tools include monitoring agents and event loggers.
In the second approach, many lines of Java code that uses the Java Reflection API could be developed, again requiring an investment of development, testing, and maintenance resources, and in addition incurring undesirable runtime performance overhead. Reflection is an API that represents (“reflects”) the classes, interfaces, and objects in the current Java Virtual Machine (JVM). Reflection can be used by programs which require the ability to examine or modify the runtime behavior of applications running in the JVM. However, because reflection involves types that are dynamically resolved, certain JVM optimizations cannot be performed. Consequently, reflective operations can have slower performance than non-reflective operations.
In addition, reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods. Therefore, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may also destroy portability. Reflective code can also break abstractions and therefore may change behavior with upgrades of the platform.
There is a need for a straightforward way to keep a data capture product up to date as applications and technology change, and that ameliorates the shortcomings of prior practices. More generally, it is desirable to provide a way to modify the operation of a program or application class during runtime.